// hello_user.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h> // For sleep

#include <bpf/libbpf.h>
#include <bpf/bpf.h>

// 包含自动生成的头文件 (通常在编译 BPF 程序后生成)
// 假设您的 BPF 程序名为 hello_bpf.bpf.o
// 如果您使用 bpftool gen skeleton，会生成 hello_bpf.skel.h
// 这里我们简化，直接加载 raw BPF object
// 实际上，更现代的写法是使用 libbpf 的 skeleton 机制

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) {
    return vfprintf(stderr, format, args);
}

static volatile sig_atomic_t exiting = 0;

void sig_int(int signo) {
    exiting = 1;
}

int main(int argc, char **argv) {
    struct bpf_object *obj;
    struct bpf_program *prog;
    struct bpf_link *link = NULL;
    int err;

    // 设置 libbpf 的日志回调
    libbpf_set_print(libbpf_print_fn);

    // 加载 BPF 对象文件
    obj = bpf_object__open_file("hello_bpf.bpf.o", NULL);
    if (!obj) {
        fprintf(stderr, "ERROR: opening BPF object file failed\n");
        return 1;
    }

    // 查找并加载 BPF 程序
    prog = bpf_object__find_program_by_name(obj, "bpf_prog");
    if (!prog) {
        fprintf(stderr, "ERROR: finding BPF program 'bpf_prog' in object file failed\n");
        bpf_object__close(obj);
        return 1;
    }

    err = bpf_object__load(obj);
    if (err) {
        fprintf(stderr, "ERROR: loading BPF object file failed\n");
        bpf_object__close(obj);
        return 1;
    }

    // 附加 BPF 程序到 tracepoint
    link = bpf_program__attach(prog);
    if (!link) {
        fprintf(stderr, "ERROR: attaching BPF program failed\n");
        bpf_object__close(obj);
        return 1;
    }

    printf("eBPF program 'bpf_prog' loaded and attached to sys_enter_execve tracepoint.\n");
    printf("Run any command in another terminal (e.g., 'ls') to see output.\n");
    printf("To stop, press Ctrl+C.\n");

    signal(SIGINT, sig_int);
    signal(SIGTERM, sig_int);

    while (!exiting) {
        sleep(1);
    }

    // 清理
    bpf_link__destroy(link);
    bpf_object__close(obj);
    printf("eBPF program unloaded.\n");

    return 0;
}